#include <linux/net.h>
#include <linux/in.h>
#include <linux/fs.h>
#include <linux/bio.h>
#include "kblock.h"

static int kblock_send(struct socket *sock,char* buf,int size)
{
    struct msghdr msg = {0};
    struct kvec vec = {0};
    
    vec.iov_base = buf;
    vec.iov_len = size;

    msg.msg_iovlen = 1;
    msg.msg_iov = (struct iovec*)&vec;
    msg.msg_flags = MSG_WAITALL | MSG_NOSIGNAL;

    return kernel_sendmsg(sock,&msg,&vec,1,size);
}

int kblock_remote_bio(struct kblock_device *device,struct bio *bio)
{
    struct data_head head = {0};
    void *iovec_mem = NULL;
    struct bio_vec *bvec = NULL;
    int i = 0;
    int total_size = 0;

    if (bio_rw(bio) != WRITE) {
        printk(KERN_INFO "remote don't handle read operation\n");
        return 0;
    }
    
    head.magic = cpu_to_be32(KBLOCK_MAGIC);
    head.type = cpu_to_be32(KBLOCK_BIO);
    head.sector = cpu_to_be64(bio->bi_sector);
    head.data_len = cpu_to_be32(bio->bi_size);
	printk(KERN_INFO "bio->bi_size %d\n",bio->bi_size);

    if (kblock_send(device->data_sock,(char*)&head,sizeof(struct data_head)) < 0) {
        printk(KERN_ERR "kblock_send head failed\n");
        return -1;
    }


    bio_for_each_segment(bvec,bio,i) {
        iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
        total_size += bvec->bv_len;
		//printk(KERN_INFO "%d:bvec offset %d len %d\n",i,bvec->bv_offset,bvec->bv_len);
        kblock_send(device->data_sock,iovec_mem,bvec->bv_len);
        kunmap(bvec->bv_page);
    }
    printk(KERN_INFO "%ld sector total size %d\n",(long)bio->bi_sector,total_size);
    return 0;
}


